package cn.handong.tool.沪房;

import org.junit.Test;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

public class 房贷月供计算器 {
    /**
     * 综合报告
     * 总贷金额：   贷款期限：
     * 总利息：
     * 商贷部分
     * 金额：   利率：
     * 总利息：
     * 公积金
     * 金额：   利率：
     * 总利息：
     *
     * 还款明细
     * 期数   还款总额   利息   本金
     */

    @Test
    public void getComprehensiveData(){
        //等额本金
        List<LoadData> loadData1 = new ArrayList<>();
        List<LoadData> loadData2 = new ArrayList<>();
        for (int i = 1; i <= 360; i++) {
//            LoadData details1 = getMonthlySupplyDetailsForEquivalentPrincipal(360, 600000, 0.031, i);
//            LoadData details2 = getMonthlySupplyDetailsForEquivalentPrincipal(360, 2170000, 0.0465, i);
            LoadData details1 = getMonthlySupplyDetailsForEquivalentPrincipalAndInterest(360, 600000, 0.031, i);
            LoadData details2 = getMonthlySupplyDetailsForEquivalentPrincipalAndInterest(360, 2170000, 0.0465, i);
            loadData1.add(details1);
            loadData2.add(details2);
        }
        int year = 2023;
        int month = 3;
        for (int i = 0; i < 360; i++) {
            if (month > 12){
                month = 1;
                year++;
            }
            System.out.print("第"+(i+1) + "期 ");
            System.out.print(" "+year+"年"+month+"月 ");
            Double totalPrincipal = getResult(loadData1.get(i).getPrincipal(),loadData2.get(i).getPrincipal());
            Double totalInterest = getResult(loadData1.get(i).getInterest(),loadData2.get(i).getInterest());
            System.out.print("本金："+totalPrincipal);
            System.out.print(" 利息："+totalInterest);
            System.out.println(" 总还款："+getResult(totalInterest,totalPrincipal));
            month++;
        }
    }

    public LoadData getMonthlySupplyDetailsForEquivalentPrincipal(int loanMonths, double loadAmount, double yearRate, int monthNum){
        double monthRate = yearRate/12; //贷款月利率
        //每月应还本金：贷款金额÷分期数
        double principalEveryMonth = getResult(loadAmount / loanMonths,0);

        //剩余本金
        double remainingPrincipal = loadAmount - principalEveryMonth*(monthNum - 1);

        //每月应还利息：剩余贷款本金*月利率
        double interestMonth = getResult(remainingPrincipal*monthRate,0);
//        System.out.print("应还本金："+principalEveryMonth);
//        System.out.print("应还利息："+interestMonth);
//        System.out.println("应还总额："+getResult(principalEveryMonth,interestMonth));
        return new LoadData(principalEveryMonth,interestMonth,getResult(principalEveryMonth,interestMonth));
    }

    public LoadData getMonthlySupplyDetailsForEquivalentPrincipalAndInterest(int loanMonths, double loadAmount, double yearRate, int monthNum){
        double monthRate = yearRate / 12; //月利率
        //月供原始数据
        double total = getResult((loadAmount * monthRate * Math.pow(1 + monthRate, loanMonths)) / (Math.pow(1 + monthRate, loanMonths) - 1),0);
        //本金
        double principal = getResult(loadAmount*(monthRate)*Math.pow(1+monthRate,monthNum-1)/(Math.pow(1+monthRate,loanMonths)-1),0);
        //利息
        double interest = getResult(total - principal,0);
//        System.out.print("应还本金："+principal);
//        System.out.print("应还利息："+interest);
//        System.out.println("应还总额："+total);
        return new LoadData(principal,interest,getResult(principal,interest));
    }

    @Test
    public void calculateMoney(){
        int yearNum = 30;
        System.out.println("等额本息");
        for (int i = 0; i < yearNum; i++) {
            System.out.print((i+1) + " 年后一次性还完 ");
            double v1 = getload1(360, 600000, 0.031, i+1);
            double v2 = getload1(360, 2170000, 0.0465, i+1);
            System.out.print(" 公积金利息 "+ v1);
            System.out.print(" 商贷利息 " + v2);
            double totalV = v1 + v2;
            DecimalFormat format = new DecimalFormat("#.00");
            totalV = Double.parseDouble(format.format(totalV));
            System.out.println(" 利息总额 " + totalV);
        }
        System.out.println("等额本金");
        for (int i = 0; i < yearNum; i++) {
            System.out.print((i+1) + " 年后一次性还完 ");
            double v1 = getLoad2(360, 600000, 0.031, i+1);
            double v2 = getLoad2(360, 2170000, 0.0465, i+1);
            System.out.print(" 公积金利息 "+ v1);
            System.out.print(" 商贷利息 " + v2);
            double totalV = v1 + v2;
            DecimalFormat format = new DecimalFormat("#.00");
            totalV = Double.parseDouble(format.format(totalV));
            System.out.println(" 利息总额 " + totalV);
        }

    }




    /**
     * 等额本息 一次性还清
     * 提前还款：还完
     *
     * 还款总额 = 提前还贷日前的最后一次还款后的剩余本金总额 + 提前还贷日前的最后一次还款日至提前还贷日止的利息。
     */


    /**
     * 等额本息 部分还款
     * 还款期限不变
     *
     * 还款总额 = 提前还贷日前的最后一次还款后的剩余本金总额 + 提前还贷日前的最后一次还款日至提前还贷日止的利息。
     */



    /**
     * 计算等额本息月供
     * @param loanMonths 贷款月数
     * @param loadAmount 贷款总额
     * @param yearRate 贷款利率
     * @return
     */
    public double getload1(int loanMonths, double loadAmount, double yearRate, int yearNum){
        double totalInterest = 0;
        double monthRate = yearRate / 12; //月利率
        DecimalFormat format = new DecimalFormat("#.00");
        //月供原始数据
        double v = (loadAmount * monthRate * Math.pow(1 + monthRate, loanMonths)) / (Math.pow(1 + monthRate, loanMonths) - 1);
        String str_v = format.format(v);
        double v_b = Double.parseDouble(str_v);
        //各期本金
        for (int i = 0; i < (yearNum * 12 + 1); i++) {
            //本金
            double bj = loadAmount*(monthRate)*Math.pow(1+monthRate,i)/(Math.pow(1+monthRate,loanMonths)-1);
            String bjStr = format.format(bj);
            double b_j = Double.parseDouble(bjStr);
            //利息
            double lx = v_b - b_j;
            String lxStr = format.format(lx);
            double l_x = Double.parseDouble(lxStr);
            totalInterest += l_x;
        }
        return Double.parseDouble(format.format(totalInterest));
    }



    /**
     * 计算等额本金月供
     * @param loanMonths 贷款月数  int loanMonths, double loadAmount, double yearRate, int yearNum
     * @param loadAmount 贷款总额
     * @param yearRate 贷款利率
     * @param yearNum 年数
     * @return
     */
    public double getLoad2(int loanMonths, double loadAmount, double yearRate, int yearNum){
        double monthRate = yearRate/12; //贷款月利率
        double principalEveryMonth1 = loadAmount / loanMonths; //每月应还本金：贷款金额÷分期数
        DecimalFormat format = new DecimalFormat("#.00");
        String str = format.format(principalEveryMonth1);
        double principalEveryMonth = Double.parseDouble(str);
        double totalInterest = 0;
        //各期利息
        for (int i = 1; i < (yearNum * 12 + 1); i++) {
            double interestEveryMonth1 = (loadAmount - principalEveryMonth*(i - 1))*monthRate; //每月应还利息：剩余贷款本金*月利率
            double interestEveryMonth = Double.parseDouble(format.format(interestEveryMonth1));
            totalInterest += interestEveryMonth;
        }
        return Double.parseDouble(format.format(totalInterest));
    }


    /**
     * 等额本息提前还完
     * @param loanMonths 贷款月数
     * @param loadAmount 贷款总额
     * @param yearRate 年利率
     * @param months 已还月数
     * @param days 距离上次还款天数
     */
    public void getload3(int loanMonths, double loadAmount, double yearRate, int months, int days){
        //还款总额 = 提前还贷日前的最后一次还款后的剩余本金总额 + 提前还贷日前的最后一次还款日至提前还贷日止的利息。
        double alreadyMoney = 0;
        DecimalFormat format = new DecimalFormat("#.00");

        double monthRate = yearRate / 12; //月利率
        double bj = 0;
        for (int i = 0; i < months; i++) {
            //第i+1个月还款本金
            bj = loadAmount*(monthRate)*Math.pow(1+monthRate,i)/(Math.pow(1+monthRate,loanMonths)-1);
            String str = format.format(bj);
            alreadyMoney += Double.parseDouble(str);
        }

        //剩余本金总额
        double remainMoney = loadAmount - alreadyMoney;
        //提前还贷日前的最后一次还款日至提前还贷日止的利息
        double remainInterest = remainMoney*(monthRate/30)*days;
        double total =remainInterest + remainMoney;
        System.out.println("还款期数："+months);
        System.out.println("已还本金："+alreadyMoney);
        System.out.println("提前还款总额："+total);
    }

    public Double getResult(double v1, double v2){
        double totalV = v1 + v2;
        DecimalFormat format = new DecimalFormat("#.00");
        return Double.parseDouble(format.format(totalV));
    }

    /**
     * 计算一下公积金一直能还到什么时候
     */
    @Test
    public void getDate(){
        double houseAccumulationFund = 78075.01; //目前住房公积金总额
        double monthlyHouseAccumulationFund = 5040;//每月公积金总数
        double monthlyPayments = 13906.11;//月供
        int currentYear = 2023;//当前年份
        int currentMonth = 2;//当前月份
        int months = 0;//历经月数

        while (houseAccumulationFund > 0){
            months++;
            houseAccumulationFund += monthlyHouseAccumulationFund;
            houseAccumulationFund -= monthlyPayments;
        }

        int finalYear = currentYear + (months + currentMonth)/12;
        int finalMonth = (months + currentMonth)%12;
        System.out.println(finalYear+"年"+finalMonth+"月");
    }

    @Test
    public void getData2(){
        List<Double> list = new ArrayList<>();
        list.add(17653.2);
        list.add(17625.53);
        list.add(17597.87);
        list.add(17570.2);
        list.add(17542.54);
        list.add(17514.88);
        list.add(17487.21);
        list.add(17459.55);
        list.add(17431.89);

        double houseAccumulationFund = 78075.01; //目前住房公积金总额
        double monthlyHouseAccumulationFund = 5040;//每月公积金总数

        int currentYear = 2023;//当前年份
        int currentMonth = 2;//当前月份
        int months = 0;//历经月数

        while (houseAccumulationFund > 0){
            months++;
            houseAccumulationFund += monthlyHouseAccumulationFund;
            houseAccumulationFund -= list.get(months);
        }

        int finalYear = currentYear + (months + currentMonth)/12;
        int finalMonth = (months + currentMonth)%12;
        System.out.println(finalYear+"年"+finalMonth+"月");

    }
}